// 云函数入口文件
const cloud = require('wx-server-sdk')

cloud.init()

const db = cloud.database()
const _ = db.command
var witnessOpenid = ""

// 云函数入口函数
exports.main = async (event, context) => {
  // ================== 获取基础信息 ===================
  // 获取房间的相关信息
  const room = (await db.collection("room").doc(event.room).get()).data
  console.log("[云数据库] [room] 房间信息: ", room)

  // 获取房间内的所有用户信息
  var users = (await db.collection("user").where({
    room: event.room
  }).get()).data
  console.log("[云数据库] [user] 房间内的用户: ", users)

  if (room.totalNum != users.length) return false

  // ================== 用户角色分配 ===================
  var result = await assignUserRole(room, users)
  if (!result) return false

  // 重新获取更新后的房间内的所有用户信息
  users = (await db.collection("user").where({
    room: event.room
  }).get()).data
  console.log("[云数据库] [user] 角色更新后 房间内的用户: ", users)
  
  // ================== 用户卡牌分配 ===================
  var result = await assignUserCard(room, users)
  if (!result) return false

  // // ================== 目击者卡牌分配 ===================
  var result = await assignScenesCard(room)
  if (!result) return false
  
  // ================== 设置用户状态 ===================
  await db.collection("user").where({
    room: room._id
  }).update({
    data: {
      status: "gaming"
    }
  })

  return true
}


// 用户角色分配
async function assignUserRole(room, users) {
  // 对用户设置角色信息
  var tempUsers = copy(users)
  try {
    await db.runTransaction(async transaction => {
      // 目击者
      await assignUserRoleItem(transaction, tempUsers, "witness")
      // 凶手
      await assignUserRoleItem(transaction, tempUsers, "killer")
      // 帮凶
      if (room.abettorNum > 0) {
        await assignUserRoleItem(transaction, tempUsers, "abettor")
      }
      // 侦探
      for (var i = 0; i < room.detectiveNum; i++) {
        await assignUserRoleItem(transaction, tempUsers, "detective")
      }
    })
  } catch (e) {
    console.log("[云数据库] [user] 更新角色信息失败: ", e)
    return []
  }
  return true
}

async function assignUserRoleItem(transaction, tempUsers, role) {
  var randomIndex = Math.floor(Math.random() * tempUsers.length)
  var user = tempUsers[randomIndex]
  await transaction.collection("user").doc(user._id).update({ data: {role: role} })
  tempUsers.splice(randomIndex, 1)
  if (role == "witness") witnessOpenid = user._openid
}

// 用户卡牌分配（手段卡、线索卡）
async function assignUserCard(room, users) {
  const cardNum = (room.totalNum - 1) * 4
  // 线索卡分发，从线索卡数据库中随机获取线索卡id组成数组
  var clueArray = []
  var clueResult = []
  for (var i = 1000; i < 1220; i++) {
    clueArray.push(i)
  }
  for (var i = 0; i < cardNum; i++) {
    var randomCardIndex = Math.floor(Math.random() * clueArray.length)
    clueResult.push(clueArray[randomCardIndex].toString())
    clueArray.splice(randomCardIndex, 1)
  }
  // 手段卡分发，从手段卡数据库中随机获取手段卡id组成数组
  var trickArray = []
  var trickResult = []
  for (var i = 2000; i < 2090; i++) {
    trickArray.push(i)
  }
  for (var i = 0; i < cardNum; i++) {
    var randomCardIndex = Math.floor(Math.random() * trickArray.length)
    trickResult.push(trickArray[randomCardIndex].toString())
    trickArray.splice(randomCardIndex, 1)
  }

  try {
    await db.runTransaction(async transaction => {
      // 根据id数组查询并获取一个 线索卡 数组
      var clueCardArr = (await transaction.collection("card_clue").where({
        _id: _.in(clueResult)
      }).get()).data
      console.log("[云数据库] [card_clue] 查询: ", clueCardArr)
      // 根据id数组查询并获取一个 手段卡 数组
      var trickCardArr = (await transaction.collection("card_trick").where({
        _id: _.in(trickResult)
      }).get()).data
      console.log("[云数据库] [card_trick] 查询: ", trickCardArr)

      // 数组乱序
      clueCardArr = shuffle(clueCardArr)
      trickCardArr = shuffle(trickCardArr)

      console.log("[users] >>> ", users)
      var cardArrIndex = 0
      // 卡牌分发并存储
      for (const item in users) {
        if (users[item].role == "witness") continue
        for (var i = 0; i < 4; i++) {
          // 线索卡分发并存储
          console.log("[cardArrIndex] >>> ", cardArrIndex)
          console.log("[clueCardArrItem] >>> ", clueCardArr[cardArrIndex])
          console.log("[trickCardArrItem] >>> ", trickCardArr[cardArrIndex])
          await transaction.collection("game_card").add({
            data: {
              openid: users[item]._openid,
              processing: true,
              cardId: clueCardArr[cardArrIndex]._id,
              cardName: clueCardArr[cardArrIndex].name,
              cardImage: clueCardArr[cardArrIndex].image,
              cardType: "clue",
              mark: false,
              selected: false,
              room: room._id
            }
          })
          // 手段卡分发并存储
          await transaction.collection("game_card").add({
            data: {
              openid: users[item]._openid,
              processing: true,
              cardId: trickCardArr[cardArrIndex]._id,
              cardName: trickCardArr[cardArrIndex].name,
              cardImage: trickCardArr[cardArrIndex].image,
              cardType: "trick",
              mark: false,
              selected: false,
              room: room._id
            }
          })
          ++cardArrIndex
        }
      }
    })
  } catch (e) {
    console.log("[云数据库] [game_card] 写入数据失败: ", e)
    return false
  }
  return true
}

// 分配场景卡
async function assignScenesCard(room) {
  var scenesArray = []
  var scenesResult = ["3000", (Math.floor(Math.random() * 8) + 3001).toString()]
  for (var i = 3009; i < 3030; i++) {
    scenesArray.push(i)
  }
  for (var i = 0; i < 7; i++) {
    var randomIndex = Math.floor(Math.random() * scenesArray.length)
    scenesResult.push(scenesArray[randomIndex].toString())
    scenesArray.splice(randomIndex, 1)
  }

  try {
    await db.runTransaction(async transaction => {
      const scenesCardArr = (await transaction.collection("card_scenes").where({
        _id: _.in(scenesResult)
      }).get()).data
      for (var i = 0; i < scenesCardArr.length; i++) {
        var serialNumber = Math.floor(Math.random() * 1000) + 1000
        var cardColor = "#2f2fff"
        if (scenesCardArr[i].type == 0) {
          serialNumber = 0
          cardColor = "#dd1515"
        }
        if (scenesCardArr[i].type == 1) {
          serialNumber = 1
          cardColor = "#a6932b"
        }
        await transaction.collection("game_scenes").add({
          data: {
            openid: witnessOpenid,
            processing: 0,
            cardId: scenesCardArr[i]._id,
            cardName: scenesCardArr[i].name,
            cardItems: scenesCardArr[i].items,
            cardType: scenesCardArr[i].type,
            cardColor: cardColor,
            selectedItem: "",
            serialNumber: serialNumber,
            room: room._id
          }
        })
      }
    })
  } catch (e) {
    console.log("[云数据库] [game_scenes] 写入数据失败: ", e)
    return false
  }
  return true
}

// 数组顺序打乱（Fisher–Yates算法）
function shuffle(arr) {
  let m = arr.length;
  while (m > 1){
      let index = Math.floor(Math.random() * m--);
      [arr[m] , arr[index]] = [arr[index] , arr[m]]
  }
  return arr;
}

function copy(array) {
  return JSON.parse(JSON.stringify(array))
}